﻿
Imports System.Threading
Imports osi.root.connector

'another implementation of circle
Public Class cycle(Of T)
    Private Const defaultSize As Int64 = 128 * 1024
    'it will only failed when thread count is over this limitation
    Private Const reservedSize As Int64 = 1024
    Private Const minSize As Int64 = (reservedSize << 1)
    Private _last As Int32
    Private _first As Int32
    Private _buff() As T

    Public Sub clear()
        _last = 0
        _first = 0
    End Sub

    Public Sub New(ByVal size As Int64)
        If size < minSize Then
            size = minSize
        End If
        ReDim _buff(minSize - 1)
        clear()
    End Sub

    Public Sub New()
        Me.New(defaultSize)
    End Sub

    Public Function buff() As T()
        Return _buff
    End Function

    Private Function index(ByVal i As Int32) As Int32
        Return i Mod _buff.Length()
    End Function

    Public Function first() As Int32
        Return index(_first)
    End Function

    Public Function last() As Int32
        Return index(_last)
    End Function

    Public Function front() As T
        Return at(first())
    End Function

    Public Function back() As T
        Return at(last())
    End Function

    Public Function push_back(ByVal i As T) As Boolean
        If full() Then
            Return False
        Else
            Dim j As Int32 = 0
            j = index(Interlocked.Increment(_last) - 1)
            k_assert(_buff(j) Is Nothing)
            copy(_buff(j), i)
            Return True
        End If
    End Function

    Public Function pop_front(ByRef i As T) As Boolean
        If empty() Then
            Return False
        Else
            Dim j As Int32 = 0
            j = index(Interlocked.Increment(_first) - 1)
            While _buff(j) Is Nothing
            End While
            copy(i, _buff(j))
            _buff(j) = Nothing
            Return True
        End If
    End Function

    Public Function availableIndex(ByVal i As Int32) As Boolean
        Return i < _buff.Length() AndAlso i >= 0
    End Function

    Default Public Property at(ByVal i As Int32) As T
        Get
            If availableIndex(i) Then
                Return _buff(i)
            Else
                Return Nothing
            End If
        End Get
        Set(ByVal value As T)
            If availableIndex(i) Then
                _buff(i) = value
            End If
        End Set
    End Property

    Public Function empty() As Boolean
        Return _last = _first
    End Function

    Public Function full() As Boolean
        Return _last = _first - reservedSize
    End Function
End Class
